package com.dongnam.quanly.web.error;

import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.apache.log4j.NDC;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dongnam.quanly.common.model.ConsoleUser;
import com.dongnam.quanly.web.JSFUtility;
import com.dongnam.quanly.web.UserBean;

@ManagedBean(name = "ErrorBean")
@ViewScoped
public class ErrorBean implements Serializable {

	private static final long serialVersionUID = 1L;

	private static final Logger logger = LoggerFactory.getLogger(ErrorBean.class);

	private Integer statusCode;
	private String referenceId;

	/**
	 * FIXME Every time ErrorBean is created, a log will be created. If user
	 * refresh the page frequently, the log size may be increased dramatically.
	 * This may be a weak point of the site.
	 */
	public ErrorBean() {
		FacesContext context = FacesContext.getCurrentInstance();
		Map<String, Object> request = context.getExternalContext().getRequestMap();

		statusCode = (Integer) request.get("javax.servlet.error.status_code");
		Throwable e = (Throwable) request.get("javax.servlet.error.exception");
		String reqUri = (String) request.get("javax.servlet.error.request_uri");
		String randHex = String.format("%X", ThreadLocalRandom.current().nextInt(1000));
		Date date = new Date();
		referenceId = new SimpleDateFormat("yyyyMMddHHmmssSSS").format(date) + "-" + randHex;

		UserBean userBean = null;
		// FIXME this may create a new session bean if it originally not exist,
		// will this session bean not removed
		userBean = JSFUtility.findBean(UserBean.class);

		NDC.push("[ErrorRef:" + referenceId + "]");
		try {
			// print user identity
			ConsoleUser user = userBean.getUser();
			logger.info("userId: {}", user == null ? null : user.getUserId());

			// print user action, if any?

			// print details
			logger.info("statusCode: {}", statusCode);
			logger.info("requestUri: {}", reqUri);
			logger.info("exceptionTrace:", e);
		} finally {
			NDC.pop();
		}
	}

	public Integer getStatusCode() {
		return statusCode;
	}

	public String getReferenceId() {
		return referenceId;
	}
}
